// UDP-客户端socket编程

#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>  //using for: atoi
#include <sys/socket.h>
#include <arpa/inet.h>
using namespace std;

int main(int argc, char* argv[])
{
    /* 利用主函数的参数 传入客户端想连接的服务端
     * ./udp_cli ip port
     * */
    if(argc != 3)  //输入参数有误
    {
        printf("use command: ./udp_cli [ip] [port]\n");
        return 0;
    }
    char* ip = argv[1];
    uint16_t port = atoi(argv[2]);

    // 1.创建套接字
    int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
    if(sock_fd < 0)
    {
        perror("socket_creat");
        return 0;
    }
    printf("sock_fd is %d\n", sock_fd);

    // 2.不推荐绑定地址信息
   
    

    // 循环发收信息
    //  (1)创建地址信息结构，提前保存服务端的地址信息
    struct sockaddr_in ser_addr;
    ser_addr.sin_family = AF_INET;
    ser_addr.sin_port = htons(port);
    
    ser_addr.sin_addr.s_addr = inet_addr(ip); //目的IP
    //ser_addr.sin_addr.s_addr = inet_addr("101.43.7.28"); //目的IP一般为公网IP
    //ser_addr.sin_addr.s_addr = inet_addr("10.0.16.3"); //（ser和cli在同一台主机）也可为为私网IP
    
    while(1)
    {
        // 3.发送数据
        //  (2)创建要发送的数据
        //  (3)调用sendto接口
        
        char buf[1024] = {0};
        printf("client：");
        fflush(stdout);
        cin >> buf;

        ssize_t send_size = sendto(sock_fd, buf, strlen(buf), 0, (struct sockaddr*)&ser_addr, sizeof(ser_addr));
        if(send_size < 0)
        {
            perror("sendto");
            return 0; 
        }

        // 4.接收数据
        //  (1)清空缓冲区来接受数据
        //  (2)调用recvfrom()接口，无需创建第3、4个出参保存服务端的地址信息
        //  (3)打印数据
        
        memset(buf, '\0', sizeof(buf));
        ssize_t recv_size = recvfrom(sock_fd, buf, sizeof(buf) - 1, 0 , NULL, NULL);
        if(recv_size < 0)
        {
            perror("recvfrom");
            continue;
        }
        printf("%s\n", buf);
    }

    // 4.关闭套接字
    close(sock_fd);
    return 0;
}
